package model

import (
	"database/sql/driver"
	"fmt"
	"log"
	"time"
)

// BaseDomain 公共字段
type BaseDomain struct {
	CreateBy   string        `gorm:"column:create_by" json:"createBy,omitempty"`     // 创建人
	// swagger:strfmt date-time
	CreateTime LocalDateTime `gorm:"column:create_time" json:"createTime,omitempty"` // 创建时间
	UpdateBy   string        `gorm:"column:update_by" json:"updateBy,omitempty"`     // 修改人
	// swagger:strfmt date-time
	UpdateTime LocalDateTime `gorm:"column:update_time" json:"updateTime,omitempty"` // 更新时间
	Remarks    string        `gorm:"column:remarks" json:"remarks,omitempty"`        // 备注
}

func IsAdmin(id int64) bool {
	return id == 1
}

// LocalDate 自定义日期 下边四个函数保证序列化与反序列化的返回格式，这里会覆盖默认的格式
//
// swagger:strfmt date
type LocalDate struct {
	time.Time
}

// LocalDateTime 自定义日期时间 下边四个函数保证序列化与反序列化的返回格式，这里会覆盖默认的格式
//
// swagger:strfmt date-time
type LocalDateTime struct {
	time.Time
}

func LoadDefaultLocation() *time.Location {
	loc, err := time.LoadLocation("Asia/Shanghai")
	if err != nil {
		loc = time.Local
	}
	return loc
}

func (t *LocalDate) UnmarshalJSON(data []byte) (err error) {
	if len(data) == 2 {
		*t = LocalDate{Time: time.Time{}}
		return
	}
	now, err := time.ParseInLocation(`"`+time.DateOnly+`"`, string(data), LoadDefaultLocation())
	*t = LocalDate{Time: now}
	return
}

func (t LocalDate) MarshalJSON() ([]byte, error) {
	if t.Time.IsZero() {
		return []byte(`""`), nil
	}
	return fmt.Appendf(nil, "\"%s\"", t.Format(time.DateOnly)), nil
}

func (t LocalDate) Value() (driver.Value, error) {
	var zeroTime time.Time
	if t.Time.UnixNano() == zeroTime.UnixNano() {
		return nil, nil
	}
	return t.Time, nil
}

// Scan value of time.Time
func (t *LocalDate) Scan(v any) error {
	value, ok := v.(time.Time)
	if ok {
		*t = LocalDate{Time: value}
		return nil
	}
	return fmt.Errorf("can not convert %v to date", v)
}

func (t *LocalDateTime) UnmarshalJSON(data []byte) (err error) {
	if len(data) == 2 {
		*t = LocalDateTime{Time: time.Time{}}
		return
	}
	now, err := time.ParseInLocation(`"`+time.DateTime+`"`, string(data), LoadDefaultLocation())
	*t = LocalDateTime{Time: now}
	return
}

func (t LocalDateTime) MarshalJSON() ([]byte, error) {
	if t.Time.IsZero() {
		//return []byte("null"), nil
		// 返回空字符串
		return []byte(`""`), nil
	}
	return fmt.Appendf(nil, "\"%s\"", t.Format(time.DateTime)), nil
}

func (t LocalDateTime) Value() (driver.Value, error) {
	var zeroTime time.Time
	if t.Time.UnixNano() == zeroTime.UnixNano() {
		return nil, nil
	}
	return t.Time, nil
}

// Scan value of time.Time
func (t *LocalDateTime) Scan(v any) error {
	value, ok := v.(time.Time)
	if ok {
		*t = LocalDateTime{Time: value}
		return nil
	}
	return fmt.Errorf("can not convert %+v to dateTime", v)
}

// LocalDateTimeNow 设置当前日期时间
//
// name: 时区名称，默认Asia/Shanghai
//
// LocalDateTime： 当前日期时间
func LocalDateTimeNow(name string) LocalDateTime {
	if name == "" {
		name = "Asia/Shanghai"
	}
	location, err := time.LoadLocation(name)
	if err != nil {
		log.Printf("LocalDateTime LoadLocation error %+v", err)
		location = time.Local
	}
	return LocalDateTime{Time: time.Now().In(location)}
}

// LocalDateNow 设置当前日期
//
// name: 时区名称，默认Asia/Shanghai
//
// LocalDate： 当前日期
func LocalDateNow(name string) LocalDate {
	if name == "" {
		name = "Asia/Shanghai"
	}
	location, err := time.LoadLocation(name)
	if err != nil {
		log.Printf("LocalDateTime LoadLocation error %+v", err)
		location = time.Local
	}
	return LocalDate{Time: time.Now().In(location)}
}

// String 返回默认的yyyy-MM-dd字符串日期
func (t LocalDate) String() string {
	if t.IsZero() {
		return ""
	}
	// 使用时区转换确保输出正确
	return t.Time.In(LoadDefaultLocation()).Format(time.DateOnly)
}

// String 返回默认的yyyy-MM-dd HH:mm:ss字符串日期
func (t LocalDateTime) String() string {
	if t.IsZero() {
		return ""
	}
	// 使用时区转换确保输出正确
	return t.Time.In(LoadDefaultLocation()).Format(time.DateTime)
}


// RouterVo 路由信息结构
type RouterVo struct {
	Name       string      `json:"name,omitempty"`       // 路由名称
	Path       string      `json:"path,omitempty"`       // 路由地址
	Hidden     bool        `json:"hidden,omitempty"`     // 是否隐藏路由，当设置 true 的时候该路由不会再侧边栏出现
	Redirect   string      `json:"redirect,omitempty"`   // 重定向地址，当设置 noRedirect 的时候该路由在面包屑导航中不可被点击
	Component  string      `json:"component,omitempty"`  // 组件地址
	AlwaysShow bool        `json:"alwaysShow,omitempty"` // 当你一个路由下面的 children 声明的路由大于1个时，自动会变成嵌套的模式--如组件页面
	Meta       *MetaVo     `json:"meta,omitempty"`
	Children   []*RouterVo `json:"children,omitempty"` // 子路由
}

// MetaVo 路由页面信息结构
type MetaVo struct {
	Title   string `json:"title"`   // 设置该路由在侧边栏和面包屑中展示的名字
	Icon    string `json:"icon"`    // 设置该路由的图标，对应路径src/assets/icons/svg
	NoCache bool   `json:"noCache"` // 设置为true，则不会被 <keep-alive>缓存
}

func NewMetaVo(menuName, menuIcon string, isCache bool) *MetaVo {
	return &MetaVo{
		Title:   menuName,
		Icon:    menuIcon,
		NoCache: isCache,
	}
}